<?php
namespace ff\database;

class Command
{

    public static $db;
    public static $dbconnect = false;
    public static $driver;
    public static $default_confkey = '';

    public function __construct( $config)
    {

        $driver = 'ff\database\mysql\mysqli';
        self::$driver = $driver;
        self::$db = new $driver;


        self::$db->set_config($config);
        self::$default_confkey = $config['default'];

    }


    public static function dbpreconfig($confkey)
    {
        if ($confkey) {
            self::$default_confkey = $confkey;
            self::$dbconnect = false;
            return true;
        }
        return false;
    }

    public static function connect($confkey = '')
    {
        if (!$confkey) {
            $confkey = self::$default_confkey;
        }

        
        self::$db->connect($confkey);
        self::$dbconnect = true;
    }

    public static function object()
    {
        return self::$db;
    }

    public static function table($table)
    {
        if (!self::$dbconnect) {
            self::connect();
        }
        return self::$db->table_name($table);
    }

    public static function select_db($dbname)
    {
        return self::$db->select_db($dbname);
    }

    public static function delete($table, $condition, $limit = 0, $unbuffered = true)
    {
        if (!self::$dbconnect) {
            self::connect();
        }
        if (empty($condition)) {
            return false;
        } elseif (is_array($condition)) {
            if (count($condition) == 2 && isset($condition['where']) && isset($condition['arg'])) {
                $where = self::format($condition['where'], $condition['arg']);
            } else {
                $where = self::implode_field_value($condition, ' AND ');
            }
        } else {
            $where = $condition;
        }
        $limit = intval($limit);
        $sql = "DELETE FROM " . self::table($table) . " WHERE $where " . ($limit > 0 ? "LIMIT $limit" : '');
        return self::query($sql, ($unbuffered ? 'UNBUFFERED' : ''));
    }

    public static function insert($table, $data, $return_insert_id = false, $replace = false, $silent = false)
    {
        if (!self::$dbconnect) {
            self::connect();
        }
        $sql = self::implode($data);

        $cmd = $replace ? 'REPLACE INTO' : 'INSERT INTO';

        $table = self::table($table);
        $silent = $silent ? 'SILENT' : '';

        return self::query("$cmd $table SET $sql", null, $silent, !$return_insert_id);
    }

    public static function update($table, $data, $condition, $unbuffered = false, $low_priority = false)
    {
        if (!self::$dbconnect) {
            self::connect();
        }
        $sql = self::implode($data);
        if (empty($sql)) {
            return false;
        }
        $cmd = "UPDATE " . ($low_priority ? 'LOW_PRIORITY' : '');
        $table = self::table($table);
        $where = '';
        if (empty($condition)) {
            $where = '1';
        } elseif (is_array($condition)) {
            $where = self::implode($condition, ' AND ');
        } else {
            $where = $condition;
        }
        $res = self::query("$cmd $table SET $sql WHERE $where", $unbuffered ? 'UNBUFFERED' : '');
        return $res;
    }

    public static function updateself($table, $data, $condition, $unbuffered = false, $low_priority = false)
    {
        if (!self::$dbconnect) {
            self::connect();
        }
        $sql = self::implodeself($data);

        if (empty($sql)) {
            return false;
        }
        $cmd = "UPDATE " . ($low_priority ? 'LOW_PRIORITY' : '');
        $table = self::table($table);
        $where = '';
        if (empty($condition)) {
            $where = '1';
        } elseif (is_array($condition)) {
            $where = self::implode($condition, ' AND ');
        } else {
            $where = $condition;
        }
        $res = self::query("$cmd $table SET $sql WHERE $where", $unbuffered ? 'UNBUFFERED' : '');
        return $res;
    }

    public static function next_autoid($table)
    {
        $table = self::table($table);
        $dbstatus = self::fetch_first("SHOW TABLE STATUS WHERE Name='{$table}';");
        return $dbstatus['Auto_increment'];
    }

    public static function insert_id()
    {
        return self::$db->insert_id();
    }

    public static function fetch($resourceid, $type = MYSQLI_ASSOC)
    {
        return self::$db->fetch_array($resourceid, $type);
    }

    public static function fetch_first($sql, $arg = array(), $silent = false)
    {
        $res = self::query($sql, $arg, $silent, false);
        $ret = self::$db->fetch_array($res);
        self::$db->free_result($res);
        return $ret ? $ret : array();
    }

    public static function fetch_all($sql, $arg = array(), $keyfield = '', $silent = false)
    {

        $data = array();
        $query = self::query($sql, $arg, $silent, false);
        while ($row = self::$db->fetch_array($query)) {
            if ($keyfield && isset($row[$keyfield])) {
                $data[$row[$keyfield]] = $row;
            } else {
                $data[] = $row;
            }
        }
        self::$db->free_result($query);
        return $data;
    }

    public static function result($resourceid, $row = 0)
    {
        return self::$db->result($resourceid, $row);
    }

    public static function result_first($sql, $arg = array(), $silent = false)
    {
        $res = self::query($sql, $arg, $silent, false);
        $ret = self::$db->result($res, 0);
        self::$db->free_result($res);
        return $ret;
    }

    public static function query($sql, $arg = array(), $silent = false, $unbuffered = false)
    {
        if (!self::$dbconnect) {
            self::connect();
        }
        if (!empty($arg)) {
            if (is_array($arg)) {
                $sql = self::format($sql, $arg);
            } elseif ($arg === 'SILENT') {
                $silent = true;

            } elseif ($arg === 'UNBUFFERED') {
                $unbuffered = true;
            }
        }
        self::checkquery($sql);

        $ret = self::$db->query($sql, $silent, $unbuffered);
        if (!$unbuffered && $ret) {
            $cmd = trim(strtoupper(substr($sql, 0, strpos($sql, ' '))));
            if ($cmd === 'SELECT') {

            } elseif ($cmd === 'UPDATE' || $cmd === 'DELETE') {
                $ret = self::$db->affected_rows();
            } elseif ($cmd === 'INSERT') {
                $ret = self::$db->insert_id();
            }
        }
        return $ret;
    }

    public static function num_rows($resourceid)
    {
        return self::$db->num_rows($resourceid);
    }

    public static function affected_rows()
    {
        return self::$db->affected_rows();
    }

    public static function free_result($query)
    {
        return self::$db->free_result($query);
    }

    public static function error()
    {
        return self::$db->error();
    }

    public static function errno()
    {
        return self::$db->errno();
    }

    public static function checkquery($sql)
    {
        return QuerySafeCheck::checkquery($sql);
    }

    public static function likesqlformat($field, $sql)
    {
        if (!$sql) {
            return false;
        }

        $sqlary = array_filter(explode(',', $sql));
        if (!$sqlary) {
            return false;
        }

        foreach ($sqlary as $i) {
            $likeary[] = "`{$field}` LIKE '%,{$i},%'";
        }
        return join(' OR ', $likeary);
    }

    public static function quote($str, $noarray = false)
    {
        if (is_string($str)) {
            return '\'' . self::$db->escape_string($str) . '\'';
        }

        if (is_int($str) or is_float($str)) {
            return '\'' . $str . '\'';
        }

        if (is_array($str)) {
            if ($noarray === false) {
                foreach ($str as &$v) {
                    $v = self::quote($v, true);
                }
                return $str;
            } else {
                return '\'\'';
            }
        }

        if (is_bool($str)) {
            return $str ? '1' : '0';
        }

        return '\'\'';
    }

    public static function quote_field($field)
    {
        if (is_array($field)) {
            foreach ($field as $k => $v) {
                $field[$k] = self::quote_field($v);
            }
        } else {
            if (strpos($field, '`') !== false) {
                $field = str_replace('`', '', $field);
            }

            $field = '`' . $field . '`';
        }
        return $field;
    }

    public static function implode($array, $glue = ',')
    {
        $sql = $comma = '';
        $glue = ' ' . trim($glue) . ' ';
        foreach ($array as $k => $v) {
            $sql .= $comma . self::quote_field($k) . '=' . self::quote($v);
            $comma = $glue;
        }
        return $sql;
    }

    public static function implodeself($array, $glue = ',')
    {
        $sql = $comma = '';
        $glue = ' ' . trim($glue) . ' ';
        foreach ($array as $k => $v) {
            $sql .= $comma . self::quote_field($k) . '=' . self::quote_field($k) . '+' . self::quote($v);
            $comma = $glue;
        }
        return $sql;
    }

    public static function implode_field_value($array, $glue = ',')
    {
        return self::implode($array, $glue);
    }

}
